from django.shortcuts import render
from django.utils import timezone
from django.views import View
from users.models import Address
from django_redis import get_redis_connection
from goods.models import SKU
import json
from django import http
from orders.models import OrderInfo,OrderGoods
from users.models import Address
from decimal import Decimal
import random
from django.db import transaction
from django.core.paginator import Paginator

# 1,订单结算页
class OrderSettlementView(View):
    def get(self,request):

        #1,查询用户地址
        addresses =  Address.objects.filter(user_id=request.user.id).all()

        #2,获取redis中选中的商品数据
        redis_conn = get_redis_connection("carts")
        cart_dict = redis_conn.hgetall(f"carts_{request.user.id}")
        selected_list = redis_conn.smembers(f"selected_{request.user.id}")

        #3,数据拼接
        sku_list = []
        total_count = 0
        total_amount = 0
        for sku_id in selected_list:
            sku = SKU.objects.get(id=sku_id)
            sku_dict = {
                "id":sku.id,
                "default_image_url":sku.default_image_url.url,
                "name":sku.name,
                "price":str(sku.price),
                "count":int(cart_dict[sku_id]),
                "amount":str(sku.price * int(cart_dict[sku_id]))
            }
            sku_list.append(sku_dict)

            #统计商品数量，商品金额
            total_count += int(cart_dict[sku_id])
            total_amount += int(sku.price * int(cart_dict[sku_id]))


        #4,携带数据渲染页面
        context = {
            "addresses":addresses,
            "skus":sku_list,
            "total_count":total_count,
            "total_amount":total_amount,
            "feight":10, # 运费
            "payment_amount":total_amount + 10 # 实付金额
        }
        return render(request,template_name='place_order.html',context=context)

# 2,订单提交
class OrderCommitView(View):

    @transaction.atomic # 开启事务
    def post(self,request):
        # 1,获取参数
        dict_data = json.loads(request.body.decode())
        address_id = dict_data.get("address_id")
        pay_method = dict_data.get("pay_method")

        # 2,校验参数（还需要校验：支付方式，地址是否存在）
        if not all([address_id,pay_method]):
            return http.JsonResponse({"code":4001,"errmsg":"参数不全"})

        # 设置回滚的保存点
        sid = transaction.savepoint()

        # 3,订单数据入库
        if pay_method == 2: # 支付宝
            status = 1
        else: # 货到付款
            status = 2

        order_id = f'{timezone.now().strftime("%Y%m%d%H%M%s")}{"%09d"%random.randint(0,999999999)}{request.user.id}'
        address = Address.objects.get(id=address_id)
        order = OrderInfo.objects.create(
            order_id=order_id, # 需要保存任何情况下都不能重复
            user = request.user,
            address = address,
            total_count = 0,
            total_amount = Decimal(0),
            feight = Decimal(0),
            pay_method=pay_method,
            status=status
        )

        # 4,订单商品入库
        redis_conn = get_redis_connection("carts")
        cart_dict = redis_conn.hgetall(f"carts_{request.user.id}")
        selected_list = redis_conn.smembers(f"selected_{request.user.id}")

        for sku_id in selected_list:
            # 4,1 获取sku,商品数量
            sku = SKU.objects.get(id=sku_id)
            count = int(cart_dict[sku_id])

            # 4,2 库存判断
            if count > sku.stock:
                transaction.savepoint_rollback(sid) # 回滚到保存点sid
                return http.JsonResponse({"code":4001,"errmsg":"库存不足"})

            # 买的人太多了，在这里卡死
            # import time
            # time.sleep(5)

            # 4,3 库存减少，销量增加
            # sku.stock -= count
            # sku.sales += count
            # sku.save()

            old_stock = sku.stock
            old_sales = sku.sales
            new_stock = old_stock - count
            new_sales = old_sales + count

            # 乐观锁，更改之前需要和之前保持一次
            ret = SKU.objects.filter(id=sku_id,stock=old_stock).update(stock=new_stock,sales=new_sales)

            # print(f"ret = {ret}")

            if ret == 0:
                transaction.savepoint_rollback(sid) # 回滚到保存点sid
                return http.JsonResponse({"code":4001,"errmsg":"并发下单失败"})

            # 4,4 创建订单商品
            OrderGoods.objects.create(
                order=order,
                sku=sku,
                count=count,
                price=sku.price
            )

            # 4,5商品订单数量，价格汇总
            order.total_count += count
            order.total_amount += int(count * sku.price)

        order.save() # 保存订单
        transaction.savepoint_commit(sid) # 提交保存点

        # 清空购物车
        redis_conn.hdel(f"carts_{request.user.id}",*selected_list)
        redis_conn.srem(f"selected_{request.user.id}",*selected_list)

        # 4,返回响应
        return http.JsonResponse({"code":0,"errmsg":"下单成功","order_id":order_id})

# 3,支付页面
class OrderSuccessView(View):
    def get(self,request):

        # 1,获取参数
        order_id = request.GET.get("order_id")
        payment_amount = request.GET.get("payment_amount")
        pay_method = request.GET.get("pay_method")

        # 2,数据校验(还需要校验，订单是否存在，支付方式是否正确，金额是否正确)
        if not all([order_id,payment_amount,pay_method]):
            return http.HttpResponseRedirect("/carts")

        # 3，携带参数，渲染页面
        context = {
            "order_id":order_id,
            "payment_amount":payment_amount,
            "pay_method":pay_method
        }

        return render(request,template_name='order_success.html',context=context)

# 4,订单信息获取
class UserOrderInfoView(View):
    def get(self,request,page_num):
        # 1,查询当前用户订单
        orders =  OrderInfo.objects.filter(user_id=request.user.id).order_by("order_id")

        # 2,分页数据查询
        paginate = Paginator(orders,2)
        page = paginate.page(page_num)

        # 3,拼接数据，渲染页面
        context = {
            "orders":page.object_list,
            "current_page":page.number,
            "total_page":paginate.num_pages
        }
        return render(request,template_name='user_center_order.html',context=context)